{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "\n",
    "def analyze_experiment_trials(trials):\n",
    "    training_SNR_dict = {'num_trials': 0,\n",
    "                         'symbols_sent': [],\n",
    "                         '3db_off': [0.0],\n",
    "                         '5db_off': [0.0],\n",
    "                         'max_num_logs': 0\n",
    "                        }\n",
    "    for trial_id, trial in trials.items():\n",
    "        meta, result_array = trial['meta'], trial['data']\n",
    "        train_SNR_db = meta['train_SNR_db']\n",
    "        batch_size = meta['batch_size']\n",
    "        num_results = meta['num_results']\n",
    "        test_SNR_dbs = meta.get('test_SNR_dbs', result_array[0]['test_SNR_dbs'])\n",
    "        if training_SNR_dict.get('test_SNR_dbs', None) is None:\n",
    "            training_SNR_dict['SNR_db_off_for']= test_SNR_dbs[4]\n",
    "            training_SNR_dict['test_SNR_dbs']=test_SNR_dbs\n",
    "        else:\n",
    "            assert training_SNR_dict['test_SNR_dbs']== test_SNR_dbs\n",
    "            assert training_SNR_dict['SNR_db_off_for']== test_SNR_dbs[4]\n",
    "        training_SNR_dict['num_trials'] += 1\n",
    "        training_SNR_dict['max_num_logs'] = max(training_SNR_dict['max_num_logs'], num_results)\n",
    "        # In order to deal with early stopping, we subtract if didn't converge,\n",
    "        # if converged early, then we don't have to fill the array\n",
    "        db5off = np.ones(training_SNR_dict['max_num_logs'])\n",
    "        db3off = np.ones(training_SNR_dict['max_num_logs'])\n",
    "        symbols_sent = training_SNR_dict['symbols_sent']\n",
    "        for i, result in enumerate(result_array):\n",
    "            assert i >= len(symbols_sent) or (result['batches_sent'] * batch_size) == symbols_sent[i]\n",
    "            symbols_sent += [result['batches_sent'] * batch_size] if i >= len(symbols_sent) else []\n",
    "            db_off = result['db_off'][4]\n",
    "            if db_off > 5.0:\n",
    "                db5off[i] -= 1.0\n",
    "            if db_off > 3.0:\n",
    "                db3off[i] -= 1.0\n",
    "        training_SNR_dict['symbols_sent'] = symbols_sent\n",
    "        # Below handles early stopping\n",
    "        t5off = training_SNR_dict['5db_off']\n",
    "        t3off = training_SNR_dict['3db_off']\n",
    "        for j in range(len(t5off), training_SNR_dict['max_num_logs']):\n",
    "            t5off = np.append(t5off, t5off[-1])\n",
    "            t3off = np.append(t3off, t3off[-1])\n",
    "        training_SNR_dict['5db_off'] = t5off + db5off\n",
    "        training_SNR_dict['3db_off'] = t3off + db3off\n",
    "        \n",
    "        trial_final_bers = np.array(result_array[-1]['test_bers'])\n",
    "        trial_final_bers = trial_final_bers[..., np.newaxis]\n",
    "        if training_SNR_dict.get('final_bers', None) is None:\n",
    "            training_SNR_dict['final_bers'] = trial_final_bers\n",
    "        else:\n",
    "            training_SNR_dict['final_bers'] = np.append(training_SNR_dict['final_bers'], trial_final_bers, axis=1)\n",
    "    num_trials = training_SNR_dict['num_trials']\n",
    "    training_SNR_dict['5db_off'] = training_SNR_dict['5db_off'] / num_trials\n",
    "    training_SNR_dict['3db_off'] = training_SNR_dict['3db_off'] / num_trials\n",
    "    sorted_bers = np.sort(training_SNR_dict['final_bers'], axis=1)\n",
    "    training_SNR_dict['BER_low'] = sorted_bers[:, num_trials * 10 // 100]\n",
    "    training_SNR_dict['BER_mid'] = sorted_bers[:, num_trials // 2]\n",
    "    training_SNR_dict['BER_high'] = sorted_bers[:, num_trials * 90 // 100]\n",
    "    return training_SNR_dict"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "import google.datalab.storage as storage\n",
    "bucket_name='torch-echo'\n",
    "bucket = storage.Bucket(bucket_name)\n",
    "assert bucket.exists()\n",
    "\n",
    "to_process =[]\n",
    "\n",
    "for obj in bucket.objects():\n",
    "    if \".npy\" in obj.key and \\\n",
    "        \"processed/\" in obj.key:\n",
    "        to_process += [obj]\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Copying file://./gradient_passing-QPSK_classic_and_neural-13.npy [Content-Type=application/octet-stream]...\n",
      "Copying file://./loss_passing-QPSK_neural_and_neural-13.npy [Content-Type=application/octet-stream]...\n",
      "Removing file://./gradient_passing-QPSK_classic_and_neural-13.npy...            \n",
      "Removing file://./loss_passing-QPSK_neural_and_neural-13.npy...                 \n",
      "/ [2/2 files][  9.6 KiB/  9.6 KiB] 100% Done                                    \n",
      "Operation completed over 2 objects/9.6 KiB.                                      \n",
      "Copying file://./gradient_passing-QPSK_classic_and_neural-4_2.npy [Content-Type=application/octet-stream]...\n",
      "Removing file://./gradient_passing-QPSK_classic_and_neural-4_2.npy...           \n",
      "/ [1/1 files][  4.9 KiB/  4.9 KiB] 100% Done                                    \n",
      "Operation completed over 1 objects/4.9 KiB.                                      \n",
      "Copying file://./gradient_passing-QPSK_classic_and_neural-8_4.npy [Content-Type=application/octet-stream]...\n",
      "Removing file://./gradient_passing-QPSK_classic_and_neural-8_4.npy...           \n",
      "/ [1/1 files][  4.8 KiB/  4.8 KiB] 100% Done                                    \n",
      "Operation completed over 1 objects/4.8 KiB.                                      \n",
      "Copying file://./gradient_passing-QPSK_neural_and_classic-13.npy [Content-Type=application/octet-stream]...\n",
      "Removing file://./gradient_passing-QPSK_neural_and_classic-13.npy...            \n",
      "/ [1/1 files][  4.8 KiB/  4.8 KiB] 100% Done                                    \n",
      "Operation completed over 1 objects/4.8 KiB.                                      \n",
      "Copying file://./gradient_passing-QPSK_neural_and_classic-4_2.npy [Content-Type=application/octet-stream]...\n",
      "Removing file://./gradient_passing-QPSK_neural_and_classic-4_2.npy...           \n",
      "/ [1/1 files][  4.8 KiB/  4.8 KiB] 100% Done                                    \n",
      "Operation completed over 1 objects/4.8 KiB.                                      \n",
      "Copying file://./gradient_passing-QPSK_neural_and_classic-8_4.npy [Content-Type=application/octet-stream]...\n",
      "Removing file://./gradient_passing-QPSK_neural_and_classic-8_4.npy...           \n",
      "/ [1/1 files][  4.8 KiB/  4.8 KiB] 100% Done                                    \n",
      "Operation completed over 1 objects/4.8 KiB.                                      \n",
      "Copying file://./gradient_passing-QPSK_neural_and_neural-13.npy [Content-Type=application/octet-stream]...\n",
      "Removing file://./gradient_passing-QPSK_neural_and_neural-13.npy...             \n",
      "/ [1/1 files][  4.8 KiB/  4.8 KiB] 100% Done                                    \n",
      "Operation completed over 1 objects/4.8 KiB.                                      \n",
      "Copying file://./gradient_passing-QPSK_neural_and_neural-4_2.npy [Content-Type=application/octet-stream]...\n",
      "Removing file://./gradient_passing-QPSK_neural_and_neural-4_2.npy...            \n",
      "/ [1/1 files][  4.9 KiB/  4.9 KiB] 100% Done                                    \n",
      "Operation completed over 1 objects/4.9 KiB.                                      \n",
      "Copying file://./gradient_passing-QPSK_neural_and_neural-8_4.npy [Content-Type=application/octet-stream]...\n",
      "Removing file://./gradient_passing-QPSK_neural_and_neural-8_4.npy...            \n",
      "/ [1/1 files][  4.8 KiB/  4.8 KiB] 100% Done                                    \n",
      "Operation completed over 1 objects/4.8 KiB.                                      \n",
      "Copying file://./loss_passing-QPSK_neural_and_classic-13.npy [Content-Type=application/octet-stream]...\n",
      "Removing file://./loss_passing-QPSK_neural_and_classic-13.npy...                \n",
      "/ [1/1 files][  4.8 KiB/  4.8 KiB] 100% Done                                    \n",
      "Operation completed over 1 objects/4.8 KiB.                                      \n",
      "Copying file://./loss_passing-QPSK_neural_and_classic-4_2.npy [Content-Type=application/octet-stream]...\n",
      "Removing file://./loss_passing-QPSK_neural_and_classic-4_2.npy...               \n",
      "/ [1/1 files][  4.8 KiB/  4.8 KiB] 100% Done                                    \n",
      "Operation completed over 1 objects/4.8 KiB.                                      \n",
      "Copying file://./loss_passing-QPSK_neural_and_classic-8_4.npy [Content-Type=application/octet-stream]...\n",
      "Removing file://./loss_passing-QPSK_neural_and_classic-8_4.npy...               \n",
      "/ [1/1 files][  4.7 KiB/  4.7 KiB] 100% Done                                    \n",
      "Operation completed over 1 objects/4.7 KiB.                                      \n",
      "Copying file://./loss_passing-QPSK_neural_and_neural-13.npy [Content-Type=application/octet-stream]...\n",
      "Removing file://./loss_passing-QPSK_neural_and_neural-13.npy...                 \n",
      "/ [1/1 files][  4.8 KiB/  4.8 KiB] 100% Done                                    \n",
      "Operation completed over 1 objects/4.8 KiB.                                      \n",
      "Copying file://./loss_passing-QPSK_neural_and_neural-4_2.npy [Content-Type=application/octet-stream]...\n",
      "Removing file://./loss_passing-QPSK_neural_and_neural-4_2.npy...                \n",
      "/ [1/1 files][  4.9 KiB/  4.9 KiB] 100% Done                                    \n",
      "Operation completed over 1 objects/4.9 KiB.                                      \n",
      "Copying file://./loss_passing-QPSK_neural_and_neural-8_4.npy [Content-Type=application/octet-stream]...\n",
      "Removing file://./loss_passing-QPSK_neural_and_neural-8_4.npy...                \n",
      "/ [1/1 files][  4.8 KiB/  4.8 KiB] 100% Done                                    \n",
      "Operation completed over 1 objects/4.8 KiB.                                      \n",
      "Copying file://./private_preamble-QPSK_neural_vs_classic-13.npy [Content-Type=application/octet-stream]...\n",
      "Removing file://./private_preamble-QPSK_neural_vs_classic-13.npy...             \n",
      "/ [1/1 files][  4.8 KiB/  4.8 KiB] 100% Done                                    \n",
      "Operation completed over 1 objects/4.8 KiB.                                      \n",
      "Copying file://./private_preamble-QPSK_neural_vs_classic-4_2.npy [Content-Type=application/octet-stream]...\n",
      "Removing file://./private_preamble-QPSK_neural_vs_classic-4_2.npy...            \n",
      "/ [1/1 files][  4.9 KiB/  4.9 KiB] 100% Done                                    \n",
      "Operation completed over 1 objects/4.9 KiB.                                      \n",
      "Copying file://./private_preamble-QPSK_neural_vs_classic-8_4.npy [Content-Type=application/octet-stream]...\n",
      "Removing file://./private_preamble-QPSK_neural_vs_classic-8_4.npy...            \n",
      "/ [1/1 files][  4.9 KiB/  4.9 KiB] 100% Done                                    \n",
      "Operation completed over 1 objects/4.9 KiB.                                      \n",
      "Copying file://./private_preamble-QPSK_neural_vs_clone-13.npy [Content-Type=application/octet-stream]...\n",
      "Removing file://./private_preamble-QPSK_neural_vs_clone-13.npy...               \n",
      "/ [1/1 files][  5.0 KiB/  5.0 KiB] 100% Done                                    \n",
      "Operation completed over 1 objects/5.0 KiB.                                      \n",
      "Copying file://./private_preamble-QPSK_neural_vs_clone-4_2.npy [Content-Type=application/octet-stream]...\n",
      "Removing file://./private_preamble-QPSK_neural_vs_clone-4_2.npy...              \n",
      "/ [1/1 files][  5.0 KiB/  5.0 KiB] 100% Done                                    \n",
      "Operation completed over 1 objects/5.0 KiB.                                      \n",
      "Copying file://./private_preamble-QPSK_neural_vs_clone-8_4.npy [Content-Type=application/octet-stream]...\n",
      "Removing file://./private_preamble-QPSK_neural_vs_clone-8_4.npy...              \n",
      "/ [1/1 files][  4.9 KiB/  4.9 KiB] 100% Done                                    \n",
      "Operation completed over 1 objects/4.9 KiB.                                      \n",
      "Copying file://./private_preamble-QPSK_neural_vs_poly-13.npy [Content-Type=application/octet-stream]...\n",
      "Removing file://./private_preamble-QPSK_neural_vs_poly-13.npy...                \n",
      "/ [1/1 files][  5.1 KiB/  5.1 KiB] 100% Done                                    \n",
      "Operation completed over 1 objects/5.1 KiB.                                      \n",
      "Copying file://./private_preamble-QPSK_neural_vs_poly-4_2.npy [Content-Type=application/octet-stream]...\n",
      "Removing file://./private_preamble-QPSK_neural_vs_poly-4_2.npy...               \n",
      "/ [1/1 files][  5.1 KiB/  5.1 KiB] 100% Done                                    \n",
      "Operation completed over 1 objects/5.1 KiB.                                      \n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Copying file://./private_preamble-QPSK_neural_vs_poly-8_4.npy [Content-Type=application/octet-stream]...\n",
      "Removing file://./private_preamble-QPSK_neural_vs_poly-8_4.npy...               \n",
      "/ [1/1 files][  5.1 KiB/  5.1 KiB] 100% Done                                    \n",
      "Operation completed over 1 objects/5.1 KiB.                                      \n",
      "Copying file://./private_preamble-QPSK_neural_vs_selfalien-13.npy [Content-Type=application/octet-stream]...\n",
      "Removing file://./private_preamble-QPSK_neural_vs_selfalien-13.npy...           \n",
      "/ [1/1 files][  5.0 KiB/  5.0 KiB] 100% Done                                    \n",
      "Operation completed over 1 objects/5.0 KiB.                                      \n",
      "Copying file://./private_preamble-QPSK_neural_vs_selfalien-4_2.npy [Content-Type=application/octet-stream]...\n",
      "Removing file://./private_preamble-QPSK_neural_vs_selfalien-4_2.npy...          \n",
      "/ [1/1 files][  5.0 KiB/  5.0 KiB] 100% Done                                    \n",
      "Operation completed over 1 objects/5.0 KiB.                                      \n",
      "Copying file://./private_preamble-QPSK_neural_vs_selfalien-8_4.npy [Content-Type=application/octet-stream]...\n",
      "Removing file://./private_preamble-QPSK_neural_vs_selfalien-8_4.npy...          \n",
      "/ [1/1 files][  4.9 KiB/  4.9 KiB] 100% Done                                    \n",
      "Operation completed over 1 objects/4.9 KiB.                                      \n",
      "Copying file://./private_preamble-QPSK_poly_vs_clone-13.npy [Content-Type=application/octet-stream]...\n",
      "Removing file://./private_preamble-QPSK_poly_vs_clone-13.npy...                 \n",
      "/ [1/1 files][  5.0 KiB/  5.0 KiB] 100% Done                                    \n",
      "Operation completed over 1 objects/5.0 KiB.                                      \n",
      "Copying file://./private_preamble-QPSK_poly_vs_clone-4_2.npy [Content-Type=application/octet-stream]...\n",
      "Removing file://./private_preamble-QPSK_poly_vs_clone-4_2.npy...                \n",
      "/ [1/1 files][  5.1 KiB/  5.1 KiB] 100% Done                                    \n",
      "Operation completed over 1 objects/5.1 KiB.                                      \n",
      "Copying file://./private_preamble-QPSK_poly_vs_clone-8_4.npy [Content-Type=application/octet-stream]...\n",
      "Removing file://./private_preamble-QPSK_poly_vs_clone-8_4.npy...                \n",
      "/ [1/1 files][  5.1 KiB/  5.1 KiB] 100% Done                                    \n",
      "Operation completed over 1 objects/5.1 KiB.                                      \n",
      "Copying file://./shared_preamble-QPSK_neural_vs_classic-13.npy [Content-Type=application/octet-stream]...\n",
      "Removing file://./shared_preamble-QPSK_neural_vs_classic-13.npy...              \n",
      "/ [1/1 files][  4.8 KiB/  4.8 KiB] 100% Done                                    \n",
      "Operation completed over 1 objects/4.8 KiB.                                      \n",
      "Copying file://./shared_preamble-QPSK_neural_vs_classic-4_2.npy [Content-Type=application/octet-stream]...\n",
      "Removing file://./shared_preamble-QPSK_neural_vs_classic-4_2.npy...             \n",
      "/ [1/1 files][  4.9 KiB/  4.9 KiB] 100% Done                                    \n",
      "Operation completed over 1 objects/4.9 KiB.                                      \n",
      "Copying file://./shared_preamble-QPSK_neural_vs_classic-8_4.npy [Content-Type=application/octet-stream]...\n",
      "Removing file://./shared_preamble-QPSK_neural_vs_classic-8_4.npy...             \n",
      "/ [1/1 files][  4.8 KiB/  4.8 KiB] 100% Done                                    \n",
      "Operation completed over 1 objects/4.8 KiB.                                      \n",
      "Copying file://./shared_preamble-QPSK_neural_vs_clone-13.npy [Content-Type=application/octet-stream]...\n",
      "Removing file://./shared_preamble-QPSK_neural_vs_clone-13.npy...                \n",
      "/ [1/1 files][  4.8 KiB/  4.8 KiB] 100% Done                                    \n",
      "Operation completed over 1 objects/4.8 KiB.                                      \n",
      "Copying file://./shared_preamble-QPSK_neural_vs_clone-4_2.npy [Content-Type=application/octet-stream]...\n",
      "Removing file://./shared_preamble-QPSK_neural_vs_clone-4_2.npy...               \n",
      "/ [1/1 files][  4.9 KiB/  4.9 KiB] 100% Done                                    \n",
      "Operation completed over 1 objects/4.9 KiB.                                      \n",
      "Copying file://./shared_preamble-QPSK_neural_vs_clone-8_4.npy [Content-Type=application/octet-stream]...\n",
      "Removing file://./shared_preamble-QPSK_neural_vs_clone-8_4.npy...               \n",
      "/ [1/1 files][  4.9 KiB/  4.9 KiB] 100% Done                                    \n",
      "Operation completed over 1 objects/4.9 KiB.                                      \n",
      "Copying file://./shared_preamble-QPSK_neural_vs_poly-13.npy [Content-Type=application/octet-stream]...\n",
      "Removing file://./shared_preamble-QPSK_neural_vs_poly-13.npy...                 \n",
      "/ [1/1 files][  4.9 KiB/  4.9 KiB] 100% Done                                    \n",
      "Operation completed over 1 objects/4.9 KiB.                                      \n",
      "Copying file://./shared_preamble-QPSK_neural_vs_poly-4_2.npy [Content-Type=application/octet-stream]...\n",
      "Removing file://./shared_preamble-QPSK_neural_vs_poly-4_2.npy...                \n",
      "/ [1/1 files][  5.0 KiB/  5.0 KiB] 100% Done                                    \n",
      "Operation completed over 1 objects/5.0 KiB.                                      \n",
      "Copying file://./shared_preamble-QPSK_neural_vs_poly-8_4.npy [Content-Type=application/octet-stream]...\n",
      "Removing file://./shared_preamble-QPSK_neural_vs_poly-8_4.npy...                \n",
      "/ [1/1 files][  4.9 KiB/  4.9 KiB] 100% Done                                    \n",
      "Operation completed over 1 objects/4.9 KiB.                                      \n",
      "Copying file://./shared_preamble-QPSK_neural_vs_selfalien-13.npy [Content-Type=application/octet-stream]...\n",
      "Removing file://./shared_preamble-QPSK_neural_vs_selfalien-13.npy...            \n",
      "/ [1/1 files][  4.9 KiB/  4.9 KiB] 100% Done                                    \n",
      "Operation completed over 1 objects/4.9 KiB.                                      \n",
      "Copying file://./shared_preamble-QPSK_neural_vs_selfalien-4_2.npy [Content-Type=application/octet-stream]...\n",
      "Removing file://./shared_preamble-QPSK_neural_vs_selfalien-4_2.npy...           \n",
      "/ [1/1 files][  4.9 KiB/  4.9 KiB] 100% Done                                    \n",
      "Operation completed over 1 objects/4.9 KiB.                                      \n",
      "Copying file://./shared_preamble-QPSK_neural_vs_selfalien-8_4.npy [Content-Type=application/octet-stream]...\n",
      "Removing file://./shared_preamble-QPSK_neural_vs_selfalien-8_4.npy...           \n",
      "/ [1/1 files][  4.9 KiB/  4.9 KiB] 100% Done                                    \n",
      "Operation completed over 1 objects/4.9 KiB.                                      \n",
      "Copying file://./shared_preamble-QPSK_poly_vs_clone-13.npy [Content-Type=application/octet-stream]...\n",
      "Removing file://./shared_preamble-QPSK_poly_vs_clone-13.npy...                  \n",
      "/ [1/1 files][  4.9 KiB/  4.9 KiB] 100% Done                                    \n",
      "Operation completed over 1 objects/4.9 KiB.                                      \n",
      "Copying file://./shared_preamble-QPSK_poly_vs_clone-4_2.npy [Content-Type=application/octet-stream]...\n",
      "Removing file://./shared_preamble-QPSK_poly_vs_clone-4_2.npy...                 \n",
      "/ [1/1 files][  4.9 KiB/  4.9 KiB] 100% Done                                    \n",
      "Operation completed over 1 objects/4.9 KiB.                                      \n",
      "Copying file://./shared_preamble-QPSK_poly_vs_clone-8_4.npy [Content-Type=application/octet-stream]...\n",
      "Removing file://./shared_preamble-QPSK_poly_vs_clone-8_4.npy...                 \n",
      "/ [1/1 files][  5.0 KiB/  5.0 KiB] 100% Done                                    \n",
      "Operation completed over 1 objects/5.0 KiB.                                      \n"
     ]
    }
   ],
   "source": [
    "from io import BytesIO, StringIO\n",
    "# print([o.key for o in to_process])\n",
    "for trials_npy in to_process:\n",
    "  identifier = trials_npy.key.split(\"/\")[-1].split(\".\")[0]\n",
    "  uri = trials_npy.uri\n",
    "  %gcs read --object $uri --variable data\n",
    "  trials = np.load(BytesIO(data)).item()\n",
    "  analysis = analyze_experiment_trials(trials)\n",
    "  np.save(identifier+\".npy\", analysis)\n",
    "  !gsutil -m mv -p  ./*.npy gs://torch-echo/analyzed/"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "dict_keys(['SNR_db_off_for', 'final_bers', 'symbols_sent', 'test_SNR_dbs', 'max_num_logs', '3db_off', 'num_trials', 'BER_high', 'BER_low', 'BER_mid', '5db_off'])"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "test = np.load(identifier+\".npy\").item()\n",
    "test.keys()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# gsutil -m cp -p  gs://torch-echo/analyzed/*.npy ./analysis/results/"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
